﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ProcessAnalysis;

namespace ProcessAnalyzerApplication
{
    public enum Performances
    {
        Cpu_Consumption_Comparison,
        Private_Memory_Use,
        Paging_Space,
        Number_Of_Thread,
        Virtual_Memory_Size,
        Phisical_Memory,
        Modules_Loaded,
        Traffic_Received,
        Traffic_Sent,
        Compression_Ratio,
        DeCompression_Ratio
    }

    public partial class Form1 : Form
    {
        private bool removingGroupFlag;
        private bool popUpActive;
        private Dictionary<string,ArrayList> applicationsLists;
        private Dictionary<string, long> priorityList;
        private string currentResults;

        public Form1()
        {
            InitializeComponent();
            this.ClientSize = new System.Drawing.Size(834, 367);
            this.ApplicationNotifyIcon.Icon = new Icon("AppIcon.ico");
            AddGraphsCheckBoxes();
            applicationsLists = new Dictionary<string, ArrayList>();
            priorityList = new Dictionary<string, long>();
            currentResults = string.Empty;
        }

        private void AddGraphsCheckBoxes()
        {
            string[] performancesNames = typeof(Performances).GetEnumNames();

            int y = 0;
            foreach (var performanceName in performancesNames)
            {
                CheckBox checkBox = new CheckBox();

                checkBox.AutoSize = true;
                checkBox.Location = new System.Drawing.Point(13, 67 - y);
                checkBox.Name = performanceName;
                checkBox.Size = new System.Drawing.Size(80, 17);
                checkBox.TabIndex = 12;
                checkBox.Text = performanceName.Replace("_"," ");
                checkBox.UseVisualStyleBackColor = true;
                y -= 25;
                GraphsGroupBox.Controls.Add(checkBox);
            }

        }

        private void ApplicationNotifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.Show();
            this.Activate();
        }

        private void Form1_Deactivate(object sender, EventArgs e)
        {
            if (!popUpActive)
            {
                this.Hide();
            }
        }

        private void AddApplicationGroupButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;
            string newGroup = new PopUpTextBox().ShowDialog();
            if (ApplicationsGroupsListBox.Items.Contains(newGroup))
            {
                MessageBox.Show("Group name exist!");
            }
            else
            {
                ApplicationsGroupsListBox.Items.Add(newGroup);
                applicationsLists.Add(newGroup, new ArrayList());
            }
            popUpActive = false;
        }

        private void RemoveApplicationGroupButton_Click(object sender, EventArgs e)
        {
            removingGroupFlag = true;
            applicationsLists.Remove(ApplicationsGroupsListBox.SelectedItem.ToString());
            ApplicationsGroupsListBox.Items.Remove(ApplicationsGroupsListBox.SelectedItem);
            ApplicationsListBox.Items.Clear();
            RemoveApplicationGroupButton.Enabled = false;
            ShowBlocksGraphsButton.Enabled = false;
            AddApplicationButton.Enabled = false;
            removingGroupFlag = false;
        }

        private void ApplicationsGroupsListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!removingGroupFlag && ApplicationsGroupsListBox.SelectedItems.Count > 0)
            {
                ApplicationsListBox.Items.Clear();
                foreach (string path in applicationsLists[ApplicationsGroupsListBox.SelectedItem.ToString()].ToArray())
                {
                    ApplicationsListBox.Items.Add(GetNameFromPath(path));
                }
                RemoveApplicationGroupButton.Enabled = true;
                ShowBlocksGraphsButton.Enabled = true;
                AddApplicationButton.Enabled = true;
                RemoveApplicationButton.Enabled = false;
            }
        }

        private void StartAndStopButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;

            if (StartAndStopButton.Text == "START")
            {
                bool isThereApplications = false;
                foreach (string key in applicationsLists.Keys)
                {
                    if (applicationsLists[key].Count > 0) isThereApplications = true;
                }
                if (!isThereApplications)
                {
                    MessageBox.Show("Choose applications");
                    return;
                }

                StatusPanel.BackColor = System.Drawing.Color.Lime;
                StartAndStopButton.Text = "STOP";
                ApplicationsPanel.Enabled = false;
                GraphsGroupBox.Enabled = false;
                ButtonsPanel.Enabled = false;
                ProcessesTimer.Start();
                ProcessesTimer_Tick(this, null);
            }
            else
            {
                StatusPanel.BackColor = System.Drawing.Color.Red;
                StartAndStopButton.Text = "START";
                ApplicationsPanel.Enabled = true;
                GraphsGroupBox.Enabled = true;
                ButtonsPanel.Enabled = true;
                ProcessesTimer.Stop();
                currentResults += ProcessAnalysis.ProcessAnalysis.resultsForPPA;
            }

            popUpActive = false;
        }

        private static string GetNameFromPath(string path)
        {
            string[] programPathArray = path.Split(new[] { '\\' });
            return programPathArray[programPathArray.Length - 1];
        }

        private void AddApplicationButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;

            OpenFileDialog OpenAllFilesDialog = new OpenFileDialog();
            // Call the ShowDialog method to show the dialog box.
            DialogResult userClickedOK = OpenAllFilesDialog.ShowDialog();

            // Process input if the user clicked OK.
            if (userClickedOK == System.Windows.Forms.DialogResult.OK)
            {
                String programPath = OpenAllFilesDialog.FileName;
                if (!string.IsNullOrEmpty(programPath))
                {
                    if (ApplicationsListBox.Items.Contains(GetNameFromPath(programPath)))
                    {
                        MessageBox.Show("Application Exist");
                    }
                    else
                    {
                        ApplicationsListBox.Items.Add(GetNameFromPath(programPath));
                        applicationsLists[ApplicationsGroupsListBox.SelectedItem.ToString()].Add(programPath);
                    }
                }
            }

            popUpActive = false;
        }

        private void RemoveApplicationButton_Click(object sender, EventArgs e)
        {
            object[] applications = applicationsLists[ApplicationsGroupsListBox.SelectedItem.ToString()].ToArray();
            foreach (string apllicationPath in applications)
            {
                if (ApplicationsListBox.SelectedItems.Contains(GetNameFromPath(apllicationPath)))
                {
                    applicationsLists[ApplicationsGroupsListBox.SelectedItem.ToString()].Remove(apllicationPath);
                }
            }

            for (int i = 0; i < ApplicationsListBox.SelectedItems.Count; i++)
            {
                ApplicationsListBox.Items.Remove(ApplicationsListBox.SelectedItems[i]);
                i--;
            }

            RemoveApplicationButton.Enabled = false;
        }

        private void ApplicationsListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ApplicationsListBox.SelectedItems.Count > 0) RemoveApplicationButton.Enabled = true;
        }

        private void Save(string path)
        {
            string fileContant = "**";

            foreach (string key in applicationsLists.Keys)
            {
                fileContant += "*" + key;
                foreach (string applicatoinPath in applicationsLists[key])
                {
                    fileContant += "," + applicatoinPath;
                }
            }

            fileContant += "**";

            foreach (string performance in typeof(Performances).GetEnumNames())
            {
                fileContant += "*" + performance + "," + ((CheckBox)GraphsGroupBox.Controls[performance]).Checked;
            }

            if (currentResults.Contains("***")) currentResults = currentResults.Replace("***", "");
            fileContant += "***" + currentResults;

            System.IO.File.WriteAllText(path, fileContant);
        }

        private void Open(string path)
        {
            try
            {
                ApplicationsGroupsListBox.Items.Clear();
                ApplicationsListBox.Items.Clear();
                applicationsLists.Clear();
                AddApplicationButton.Enabled = false;
                RemoveApplicationButton.Enabled = false;
                RemoveApplicationGroupButton.Enabled = false;
                ShowBlocksGraphsButton.Enabled = false;
                currentResults = string.Empty;

                string[] configurations = System.IO.File.ReadAllText(path).Split(new[] { "***" }, StringSplitOptions.RemoveEmptyEntries);
                string[] applicationsGroups = configurations[0].Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
                string[] selectedGrahps = configurations[1].Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
                if (configurations.Length > 2)
                {
                    currentResults = configurations[2];
                }
                else
                {
                    currentResults = string.Empty;
                }

                foreach (string group in applicationsGroups)
                {
                    string[] applications = group.Split(new[] { ',' });
                    ApplicationsGroupsListBox.Items.Add(applications[0]);
                    applicationsLists.Add(applications[0], new ArrayList());
                    for (int i = 1; i < applications.Length; i++)
                    {
                        applicationsLists[applications[0]].Add(applications[i]);
                    }
                }

                foreach (string graph in selectedGrahps)
                {
                    string[] graphCheckBox = graph.Split(new[] { ',' });
                    ((CheckBox)GraphsGroupBox.Controls[graphCheckBox[0]]).Checked = Boolean.Parse(graphCheckBox[1]);
                }
            }
            catch
            {
                MessageBox.Show("Bad file");
            }
        }

        private void SaveButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;

            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "PAA Files (.paa)|*.paa";
            DialogResult userClickedOK = saveFileDialog.ShowDialog();
            if (userClickedOK == System.Windows.Forms.DialogResult.OK)
            {
                if (!string.IsNullOrEmpty(saveFileDialog.FileName))
                {
                    Save(saveFileDialog.FileName);
                }
            }

            popUpActive = false;
        }

        private void OpenButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;

            OpenFileDialog OpenAllFilesDialog = new OpenFileDialog();
            OpenAllFilesDialog.Filter = "PAA Files (.paa)|*.paa";

            // Call the ShowDialog method to show the dialog box.
            DialogResult userClickedOK = OpenAllFilesDialog.ShowDialog();

            // Process input if the user clicked OK.
            if (userClickedOK == System.Windows.Forms.DialogResult.OK)
            {
                String programPath = OpenAllFilesDialog.FileName;
                if (!string.IsNullOrEmpty(programPath))
                {
                    Open(programPath);
                }
            }

            popUpActive = false;
        }

        private void CleanButton_Click(object sender, EventArgs e)
        {
            ApplicationsGroupsListBox.Items.Clear();
            ApplicationsListBox.Items.Clear();
            applicationsLists.Clear();
            AddApplicationButton.Enabled = false;
            RemoveApplicationButton.Enabled = false;
            RemoveApplicationGroupButton.Enabled = false;
            ShowBlocksGraphsButton.Enabled = false;
            currentResults = string.Empty;

            foreach (var checkBoxGraph in GraphsGroupBox.Controls)
            {
                if (checkBoxGraph is CheckBox)
                {
                    ((CheckBox)checkBoxGraph).Checked = false;
                }
            }
        }

        private void ExitButton_Click(object sender, EventArgs e)
        {
            
            Close();
        }

        private void ProcessesTimer_Tick(object sender, EventArgs e)
        {
            long minPriority = long.MaxValue;
            string pathToRun = string.Empty;

            foreach (string key in applicationsLists.Keys)
            {
                foreach (string programPath in applicationsLists[key])
                {
                    if (!priorityList.Keys.Contains<string>(programPath))
                    {
                        priorityList.Add(programPath, 0);
                    }

                    string[] programPathArray = GetNameFromPath(programPath).Split(new[] { '.' });
                    string[] programNameArray = programPathArray.SubArray(0, programPathArray.Length - 1);
                    string programName = String.Join(".", programNameArray);
                    var processArray = System.Diagnostics.Process.GetProcessesByName(programName);

                    if (priorityList[programPath] < minPriority && processArray.Length > 0)
                    {
                        minPriority = priorityList[programPath];
                        pathToRun = programPath;
                    }
                }
            }

            if (!string.IsNullOrEmpty(pathToRun))
            {
                priorityList[pathToRun] = priorityList[pathToRun] + 1;
                ProcessAnalysis.ProcessAnalysis processAnalysis = new ProcessAnalysis.ProcessAnalysis();
                processAnalysis.AddProgram(pathToRun);
                processAnalysis.SetProcessesRunningTime(5);
                processAnalysis.SelectRow(0);
                processAnalysis.RunBtnClick(this, null);
            }
        }

        private void ShowBlocksGraphsButton_Click(object sender, EventArgs e)
        {
            popUpActive = true;

            Dictionary<string, ArrayList> numbersList = new Dictionary<string, ArrayList>();
            Dictionary<string, ArrayList> sumList = new Dictionary<string, ArrayList>();
            ArrayList applicatoinsNames = new ArrayList();
            foreach (var checkBoxGraph in GraphsGroupBox.Controls)
            {
                if (checkBoxGraph is CheckBox && ((CheckBox)checkBoxGraph).Checked)
                {
                    sumList.Add(((CheckBox)checkBoxGraph).Text, new ArrayList());
                    numbersList.Add(((CheckBox)checkBoxGraph).Text, new ArrayList());
                }
            }

            string groupName = ApplicationsGroupsListBox.SelectedItem.ToString();
            string[] resultsList = currentResults.Split(new[] { "**" }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string result in resultsList)
            {
                string[] currentResultList = result.Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
                if (applicationsLists[groupName].Contains(currentResultList[0]))
                {
                    if (!applicatoinsNames.Contains(currentResultList[0])) applicatoinsNames.Add(currentResultList[0]);
                    int appIndex = applicatoinsNames.IndexOf(currentResultList[0]);

                    for (int i = 1; i < currentResultList.Length; i++)
                    {
                        string[] pointsList = currentResultList[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        string performanceName = pointsList[0].Replace('_', ' ');
                        if (sumList.Keys.Contains<string>(performanceName))
                        {
                            for (int j = 1; j < pointsList.Length; j++)
                            {
                                if (sumList[performanceName].Count <= appIndex)
                                {
                                    sumList[performanceName].Add(Double.Parse(pointsList[j]));
                                    numbersList[performanceName].Add(1);
                                }
                                else
                                {
                                    sumList[performanceName][appIndex] =
                                        Double.Parse(sumList[performanceName][appIndex].ToString()) + 
                                        Double.Parse(pointsList[j]);
                                    numbersList[performanceName][appIndex] =
                                        Int32.Parse(numbersList[performanceName][appIndex].ToString()) + 1;
                                }
                            }
                        }
                    }
                }
            }

            foreach (string key in sumList.Keys)
            {
                for (int i = 0; i < sumList[key].Count; i++)
                {
                    sumList[key][i] = Double.Parse(sumList[key][i].ToString()) / Double.Parse(numbersList[key][i].ToString());
                }
            }

            GraphsDialog graphsDialog = new GraphsDialog(sumList, applicatoinsNames);
            graphsDialog.ShowDialog();

            popUpActive = false;
        }
    }
}
